/*
 * Copyright (C) 2015 Michele Zanella <it.polimi.meteoCal>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package it.polimi.meteoCal.control;

import it.polimi.meteoCal.boundary.BadWeatherNotificationFacade;
import it.polimi.meteoCal.boundary.EventFacade;
import it.polimi.meteoCal.boundary.RequestFacade;
import it.polimi.meteoCal.boundary.SuggestionFacade;
import it.polimi.meteoCal.boundary.UpdatesFacade;
import it.polimi.meteoCal.boundary.UsersFacade;
import it.polimi.meteoCal.control.util.DateUtil;
import it.polimi.meteoCal.entity.BadWeatherNotification;
import it.polimi.meteoCal.entity.Calendar;
import it.polimi.meteoCal.entity.Event;
import it.polimi.meteoCal.entity.Request;
import it.polimi.meteoCal.entity.Suggestion;
import it.polimi.meteoCal.entity.Updates;
import it.polimi.meteoCal.entity.Users;
import it.polimi.meteoCal.presentation.UsersView;
import java.util.Date;
import java.util.List;
import javax.ejb.EJB;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.inject.Inject;

/**
 *
 * @author Michele Zanella <it.polimi.meteoCal>
 */
@Startup
@Singleton
public class NotificationManager {

    @EJB
    private UsersFacade usersFacade;
    @EJB
    private RequestFacade requestFacade;
    @EJB
    private BadWeatherNotificationFacade badWeatherNotificationFacade;
    @EJB
    private UpdatesFacade updatesFacade;
    @EJB
    private SuggestionFacade suggestionFacade;
    @EJB
    private EventFacade eventFacade;
    @Inject
    private UsersView usersView;

    /**
     * Creates a requests for the invited users. If an user is deleted from the
     * invited the request is removed. If the user has been already invited no
     * more requests are created.
     *
     * @param invitated a list with the new invited users
     * @param oldInvited a list with the old invited users
     * @param event
     */
    public void createRequestsForInvitedUser(List<Users> invitated, List<Users> oldInvited, Event event) {
        // Remove users that are not invited any more
        if (!(invitated == null || oldInvited == null)) {
            for (Users u : oldInvited) {
                if (!invitated.contains(u)) {
                    requestFacade.remove(u.getRequest(event));
                    u.removeRequest(u.getRequest(event));
                }
            }
            // Create requests for new invited users
            for (Users u : invitated) {
                if (!hasRequestForThisEvent(u, event)) {
                    u.addRequest(new Request(event, u));
                }
            }
        }
    }

    /**
     * Creates the bad weather notification for the going users
     *
     * @param event
     */
    public void createBadWeatherNotification(Event event) {
        for (Calendar c : event.getGoingUsers()) {
            if (c.getUser().getBadWeatherNotification(event) != null) {
                badWeatherNotificationFacade.remove(c.getUser().getBadWeatherNotification(event));
                c.getUser().removeBadWeatherNotification(c.getUser().getBadWeatherNotification(event));

            }
            c.getUser().addBadWeatherNotification(new BadWeatherNotification(event, c.getUser()));
            usersFacade.edit(c.getUser());
        }
        //bwn.setUsersList(event.getGoingUsers());
        //badWeatherNotificationFacade.create(bwn);
    }

    /**
     * Creates the update notification for the going users except the creator
     *
     * @param event
     */
    public void createUpdateForGoingUser(Event event) {
        for (Calendar c : eventFacade.getGoingUsers(event)) {
            if (!c.getUser().equals(usersView.getLoggedUser())) {
                if (c.getUser().getUpdate(event) != null) {
                    updatesFacade.remove(c.getUser().getUpdate(event));
                    c.getUser().removeUpdate(c.getUser().getUpdate(event));

                }
                c.getUser().addUpdate(new Updates(event, c.getUser()));
            }
        }
    }

    /**
     * Creates a suggestion for the creator
     *
     * @param event
     * @param suggestedDate
     */
    public void createSuggestionForCreator(Event event, Date suggestedDate) {
        Users creator = event.getCreatedBy();
        if (creator.getSuggestion(event) != null) {
            suggestionFacade.remove(creator.getSuggestion(event));
            creator.removeSuggestion(creator.getSuggestion(event));
        }
        event.getCreatedBy().addSuggestion(new Suggestion(event, event.getCreatedBy(), suggestedDate, DateUtil.sumDayToDate(suggestedDate, DateUtil.eventPeriod(event.getStartDate(), event.getEndDate()) - 1)));
        //System.out.println("Date suggested: " + suggestedDate + " to:" + DateUtil.sumDayToDate(suggestedDate, DateUtil.eventPeriod(event.getStartDate(), event.getEndDate())));
        usersFacade.edit(event.getCreatedBy());
    }
    /*
     private boolean hasBWNForThisEvent(Users user, Event event) {
     for (BadWeatherNotification bwn : user.getBadWeatherNotificationsReceived()) {
     if (bwn.getEvent().equals(event)) {
     return true;
     }
     }
     return false;
     }*/

    private boolean hasRequestForThisEvent(Users user, Event event) {
        for (Request r : user.getRequestsReceived()) {
            if (r.getEvent().equals(event)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Removes all the requests for the invited users of an event
     *
     * @param usersList
     * @param event
     */
    public void removeRequestForInvitedUser(List<Users> usersList, Event event) {
        for (Users u : usersList) {
            requestFacade.remove(u.getRequest(event));
            u.removeRequest(u.getRequest(event));
        }
    }

    /**
     * Removes all the bad weather notification for the event's going users
     *
     * @param goingUsers
     * @param event
     */
    public void removeBWNForGoingUser(List<Users> goingUsers, Event event) {
        for (Users c : goingUsers) {
            if (c.getBadWeatherNotification(event) != null) {
                badWeatherNotificationFacade.remove(c.getBadWeatherNotification(event));
                c.removeBadWeatherNotification(c.getBadWeatherNotification(event));
            }
        }
        if (event.getCreatedBy().getBadWeatherNotification(event) != null) {
            badWeatherNotificationFacade.remove(event.getCreatedBy().getBadWeatherNotification(event));
            event.getCreatedBy().removeBadWeatherNotification(event.getCreatedBy().getBadWeatherNotification(event));
        }
    }

    /**
     * Removes all the updates for an event
     *
     * @param event
     */
    public void removeUpdateForGoingUser(List<Users> goingUsers, Event event) {
        for (Users c : goingUsers) {
            if (c.getUpdate(event) != null) {
                updatesFacade.remove(c.getUpdate(event));
                c.removeUpdate(c.getUpdate(event));
            }
        }
        if (event.getCreatedBy().getUpdate(event) != null) {
            updatesFacade.remove(event.getCreatedBy().getUpdate(event));
            event.getCreatedBy().removeUpdate(event.getCreatedBy().getUpdate(event));
        }
    }

    /**
     * Removes all suggestion for an event
     *
     * @param event
     */
    public void removeSuggestionForCreator(Event event) {
        if (event.getCreatedBy().getSuggestion(event) != null) {
            suggestionFacade.remove(event.getCreatedBy().getSuggestion(event));
        }
    }

    public void removeAllByEvent(Event event) {
        requestFacade.removeAllByEvent(event);
        suggestionFacade.removeAllByEvent(event);
        badWeatherNotificationFacade.removeAllByEvent(event);
        updatesFacade.removeAllByEvent(event);
    }
}
